package com.mtw.bbs.bbsUser.utils;

import com.github.wujun234.uid.utils.DockerUtils;
import com.github.wujun234.uid.utils.NetUtils;
import com.github.wujun234.uid.worker.DisposableWorkerIdAssigner;
import com.github.wujun234.uid.worker.WorkerIdAssigner;
import com.github.wujun234.uid.worker.WorkerNodeType;
import com.github.wujun234.uid.worker.dao.WorkerNodeDAO;
import com.github.wujun234.uid.worker.entity.WorkerNodeEntity;
import org.apache.commons.lang.math.RandomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;


/**
 * uid生成
 */
@Component
public class DisposableWorkerIdAssignerImpl implements WorkerIdAssigner {

    private static final Logger LOGGER = LoggerFactory.getLogger(DisposableWorkerIdAssigner.class);
    @Autowired
    private WorkerNodeDAO workerNodeDAO;



    @Transactional(
            rollbackFor = {Exception.class}
    )
    public long assignWorkerId() {
        WorkerNodeEntity workerNodeEntity = this.buildWorkerNode();
        WorkerNodeEntity oldWorkerNode = this.workerNodeDAO.getWorkerNodeByHostPort(workerNodeEntity.getHostName(), workerNodeEntity.getPort());
        if (null != oldWorkerNode) {
            return oldWorkerNode.getId();
        } else {
            this.workerNodeDAO.addWorkerNode(workerNodeEntity);
            LOGGER.info("Add worker node:" + workerNodeEntity);
            return workerNodeEntity.getId();
        }
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    public long assignFakeWorkerId() {
        return this.buildFakeWorkerNode().getId();
    }

    private WorkerNodeEntity buildWorkerNode() {
        WorkerNodeEntity workerNodeEntity = new WorkerNodeEntity();
        if (DockerUtils.isDocker()) {
            workerNodeEntity.setType(WorkerNodeType.CONTAINER.value());
            workerNodeEntity.setHostName(DockerUtils.getDockerHost());
            workerNodeEntity.setPort(DockerUtils.getDockerPort());
        } else {
            workerNodeEntity.setType(WorkerNodeType.ACTUAL.value());
            workerNodeEntity.setHostName(NetUtils.getLocalAddress());
            workerNodeEntity.setPort(System.currentTimeMillis() + "-" + RandomUtils.nextInt(100000));
        }

        return workerNodeEntity;
    }

    private WorkerNodeEntity buildFakeWorkerNode() {
        WorkerNodeEntity workerNodeEntity = new WorkerNodeEntity();
        workerNodeEntity.setType(WorkerNodeType.FAKE.value());
        if (DockerUtils.isDocker()) {
            workerNodeEntity.setHostName(DockerUtils.getDockerHost());
            workerNodeEntity.setPort(DockerUtils.getDockerPort() + "-" + RandomUtils.nextInt(100000));
        } else {
            workerNodeEntity.setHostName(NetUtils.getLocalAddress());
            workerNodeEntity.setPort(System.currentTimeMillis() + "-" + RandomUtils.nextInt(100000));
        }

        return workerNodeEntity;
    }
}
